import { mapRecursively } from '@/utils/array-recursion'

export type Logic = '' | '与' | '或'

export type SimpleSecurity = {
  logic?: Logic
  codes: string[]
}


export type ApiResource = {
    id: number
    name: string
    menuItemId: number
    menuItemName: string
    menuItemIcon?: string
    permissions: string | SimpleSecurity
    menuItemPermission?: string
    parentIdMenuItemId?: number
    roleRequirement?: SimpleSecurity
    permissionRequirement: SimpleSecurity
}

export type Resource = {
    id: number
    key: string
    name: string
    icon?: string
    permission?: string
    permissions?: string | SimpleSecurity
    type: 'Page' | 'Directory' | 'Api'
    roleRequirement?: SimpleSecurity
    permissionRequirement?: SimpleSecurity
    apis?: ApiResource[]
    parentId?: number
    children?: Resource[]
}


export function parseSecurityCodes(_codes: string): SimpleSecurity {
  let logic: Logic = '与'
  let codes = _codes.split('&&')
  if (codes.length == 1) {
    codes = codes[0].split('||')
    if (codes.length == 1) {
      logic = ''
    } else {
      logic = '或'
    }
  }
  return {
    logic,
    codes
  }
}


export function matchAnyPermission(ownedPermission: string, neededPermissions: string[]): boolean {
  return neededPermissions.find(neededPermission => {
    return matchPermission(ownedPermission, neededPermission)
  }) != undefined
}




export function matchPermission(ownedPermission: string, neededPermission: string): boolean {
  const permissionParts = neededPermission.split(":");
  const _permissionParts = ownedPermission.split(":");
  const min = Math.min(permissionParts.length, _permissionParts.length);
  for (let i = 0; i < min; i++) {
    const _permissionPart = _permissionParts[i];
    const permissionPart = permissionParts[i];
    if ("*" === _permissionPart) {
      //当前段匹配
    } else if ("**" === _permissionPart) {
      //全部匹配
      return true;
    } else if (_permissionPart != permissionPart) {
      //当前段不匹配，整体不匹配
      return false;
    }
  }
  return permissionParts.length <= _permissionParts.length;
}

export function hasPermission(permissions: Array<string>, neededPermission: string): boolean {
  const permissionParts = neededPermission.split(":");
  return permissions.find((_permission) => {
    const _permissionParts = _permission.split(":");
    const min = Math.min(permissionParts.length, _permissionParts.length);
    for (let i = 0; i < min; i++) {
      const _permissionPart = _permissionParts[i];
      const permissionPart = permissionParts[i];
      if ("*" === _permissionPart) {
        //当前段匹配
      } else if ("**" === _permissionPart) {
        //全部匹配
        return true;
      } else if (_permissionPart != permissionPart) {
        //当前段不匹配，整体不匹配
        return false;
      }
    }
    return permissionParts.length <= _permissionParts.length;
  }) != undefined;
}

export function matchRoles(ownedRoles: string[], neededRoleSecurity: SimpleSecurity = {codes: []}): boolean{
  if(neededRoleSecurity == null) {
    neededRoleSecurity = {codes: []}
  }
  if(neededRoleSecurity.logic == '与') {
    return neededRoleSecurity.codes.every((code) => {
      return ownedRoles.includes(code);
    })
  } else {
    return neededRoleSecurity.codes.length == 0 || neededRoleSecurity.codes.find((code) => {
      return ownedRoles.includes(code);
    }) != undefined
  }
}

export type PermissionMatchResult = {
  editable: boolean
  matched: boolean
}

export function matchPermissions(ownedRolePermissions: string[] = [], ownedPermissions: string[] = [], neededPermissionSecurity: SimpleSecurity= {codes: []}): PermissionMatchResult{

  if(!neededPermissionSecurity?.codes?.length) {
    return {
      editable: false,
      matched: true
    }
  } else if(neededPermissionSecurity.logic == '与') {
    const matchedOwnedRolePermissions = ownedRolePermissions.filter((code) => {
      return matchAnyPermission(code, neededPermissionSecurity.codes)
    })

    const extraPermissions = neededPermissionSecurity.codes.filter(code => {
      return !hasPermission(matchedOwnedRolePermissions, code)
    })

    return {
      editable: extraPermissions.length > 0,
      matched: extraPermissions.every((code) => {
        return hasPermission(ownedPermissions, code)
      })
    }
  }else {
    const matchedPermission = neededPermissionSecurity.codes.find((code) => {
      return hasPermission(ownedRolePermissions, code)
    })
    if(matchedPermission) {
      return {
        editable: false,
        matched: true
      }
    }else {
      return {
        editable: true,
        matched: neededPermissionSecurity.codes.find((code) => {
          return hasPermission(ownedPermissions, code)
        }) != undefined
      }
    }
  }
}




export function formatMenuItemApiTree(menuItemApiTree: Resource[]): Resource[] {
    return mapRecursively(menuItemApiTree, (currentValue) => {
        if (currentValue.type == 'Page' && Array.isArray(currentValue.apis)) {
            currentValue.children = currentValue.apis.map((api) => {
                return {
                    type: 'Api',
                    key: api.menuItemId + '' + api.id,
                    id: api.id,
                    name: api.name,
                    parentId: api.menuItemId,
                    roleRequirement: api.roleRequirement,
                    permissionRequirement: api.permissionRequirement,
                }
            })
        }

        if (currentValue.type == 'Api') {
            return currentValue
        } else {
            const menuItem: Resource = { ...currentValue, key: currentValue.id + '' }
            if (menuItem.permission) {
                menuItem.permissions = {
                    codes: [menuItem.permission]
                }
            }
            return menuItem
        }
    })
}